package com.smile.service.impl;

//import cn.dev33.satoken.stp.StpUtil;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smile.api.OperateLogApi;
import com.smile.commons.action.ActionUtils;
import com.smile.commons.constant.StateConstant;
import com.smile.commons.md5.MD5Util;
import com.smile.commons.page.MyBatisPlusPageConverter;
import com.smile.mapper.OrganizationMapper;
import com.smile.mapper.RoleMapper;
import com.smile.mapper.UserMapper;
import com.smile.model.domain.SmilePlusOrganization;
import com.smile.model.domain.SmilePlusRole;
import com.smile.model.domain.SmilePlusUser;
import com.smile.model.dto.request.AddUserRequestDTO;
import com.smile.model.dto.request.EditUserRequestDTO;
import com.smile.model.dto.request.GetUserInfoByUserNameRequestDTO;
import com.smile.model.dto.request.GetUserListRequestDTO;
import com.smile.model.response.response.GetUserByIdResponseDTO;
import com.smile.model.response.response.GetUserInfoByUserNameResponseDTO;
import com.smile.model.response.response.GetUserListResponseDTO;
import com.smile.model.response.response.GetUserSimpleInfoResponseDTO;
import com.smile.request.AddOperateLogRequest;
import com.smile.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toMap;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private OperateLogApi operateLogApi;

    @Resource
    private OrganizationMapper organizationMapper;

    /**
     * 检查是否为超级管理员账号（ID为1）
     * @param userId 用户ID
     * @param operation 操作类型（用于错误提示）
     */
    private void checkSuperAdminProtection(Long userId, String operation) {
        if (userId == 1) {
            throw new RuntimeException("超级管理员账号无法" + operation);
        }
    }

    @Override
    public Boolean addUser(AddUserRequestDTO addUserRequestDTO) {

        Long organizationId = addUserRequestDTO.getOrganizationId();
        SmilePlusOrganization smilePlusOrganization = organizationMapper.selectById(organizationId);

        if (smilePlusOrganization == null || smilePlusOrganization.getDeleteStatus() == Boolean.TRUE) {
            throw new RuntimeException("组织已删除，请重新选择");
        }

        // 异步校验角色是否存在
        if (ObjectUtil.isNotNull(addUserRequestDTO.getRoleId())) {
            SmilePlusRole role = roleMapper.selectById(addUserRequestDTO.getRoleId());
            if (role == null) {
                throw new RuntimeException("角色已删除，请重新选择");
            }
        }

        Long startTime = System.nanoTime();
        QueryWrapper<SmilePlusUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name", addUserRequestDTO.getUserName());
        SmilePlusUser smilePlusUser1 = userMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNotEmpty(smilePlusUser1)) {
            if (smilePlusUser1.getDeleteStatus()) {
                userMapper.deleteById(smilePlusUser1.getUserId());
            } else {
                log.error("您添加的{}用户已存在", addUserRequestDTO.getUserName());
                throw new RuntimeException("该用户已存在!");
            }
        }


        SmilePlusUser smilePlusUser = new SmilePlusUser();
        BeanUtil.copyProperties(addUserRequestDTO, smilePlusUser);
        String salt = MD5Util.generateSalt();
        smilePlusUser.setCreateTime(LocalDateTime.now());
        smilePlusUser.setModifyTime(LocalDateTime.now());
        smilePlusUser.setSalt(salt);
        smilePlusUser.setUserType(1);
        smilePlusUser.setUserId(Long.valueOf(StpUtil.getLoginId().toString()));
        smilePlusUser.setDeleteStatus(Boolean.FALSE);

        smilePlusUser.setPassword(MD5Util.md5WithSalt(addUserRequestDTO.getPassword(), salt));
        userMapper.insert(smilePlusUser);
        Long endTime = System.nanoTime();

        AddOperateLogRequest addOperateLogRequest = new AddOperateLogRequest();
        addOperateLogRequest.setOperateModule("用户模块");
        addOperateLogRequest.setOperateName("添加用户");
        addOperateLogRequest.setOperateResult(Boolean.TRUE);
        addOperateLogRequest.setUserId(Long.valueOf(StpUtil.getLoginId().toString()));
        addOperateLogRequest.setOperateType(1);
        addOperateLogRequest.setIpAddress(ActionUtils.getIpInfo());
        addOperateLogRequest.setExplorer(ActionUtils.getExplorerInfo());
        addOperateLogRequest.setTimes(endTime - startTime);
        operateLogApi.addOperateLogRequest(addOperateLogRequest);

        return Boolean.TRUE;
    }

    public static void main(String[] args) {
//        System.out.println(StrUtil.isBlank("1"));
        String salt = MD5Util.generateSalt();
        System.out.println("salt = " + salt);
        System.out.println("MD5Util.md5WithSalt(\"FEISUAN888\", salt) = " + MD5Util.md5WithSalt("FEISUAN888", salt));
    }

    @Override
    public Page<GetUserListResponseDTO> getUserList(GetUserListRequestDTO getUserListRequestDTO) {
        QueryWrapper<SmilePlusUser> queryWrapper = new QueryWrapper<>();

        if (StrUtil.isNotBlank(getUserListRequestDTO.getUserName())) {
//            return Boolean.FALSE;
            queryWrapper.eq("user_name", getUserListRequestDTO.getUserName());
        }
        if (StrUtil.isNotBlank(getUserListRequestDTO.getRealName())) {
            queryWrapper.eq("real_name", getUserListRequestDTO.getRealName());
        }

        if (StrUtil.isNotBlank(getUserListRequestDTO.getMobile())) {
            queryWrapper.eq("mobile", getUserListRequestDTO.getMobile());
        }
        if (ObjectUtil.isNotNull(getUserListRequestDTO.getStatus())) {
            queryWrapper.eq("status", getUserListRequestDTO.getStatus());
        }

        if (ObjectUtil.isNotNull(getUserListRequestDTO.getOrganizationId())) {
            queryWrapper.eq("organization_id", getUserListRequestDTO.getOrganizationId());
        }

        queryWrapper.eq("delete_status", Boolean.FALSE);
        queryWrapper.orderByDesc("create_time");
        queryWrapper.orderByAsc("id");

        Page<SmilePlusUser> smilePlusUserPage = userMapper.selectPage(new Page<>(getUserListRequestDTO.getCurrentPage().longValue(), getUserListRequestDTO.getPageSize().longValue()), queryWrapper);

        List<SmilePlusRole> smilePlusRoles = roleMapper.selectList(null);


        Page<GetUserListResponseDTO> getUserListResponseDTOPage = MyBatisPlusPageConverter.convertPage(smilePlusUserPage, GetUserListResponseDTO.class);
        List<GetUserListResponseDTO> collect1 = getUserListResponseDTOPage.getRecords().stream().map(i -> {
                    Long roleId = i.getRoleId();
                    List<SmilePlusRole> collect = smilePlusRoles.stream().filter(i1 -> Objects.equals(i1.getId(), roleId)).map(i2 -> i2).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(collect)) {
                        String roleName = collect.get(0).getRoleName();
                        i.setRoleName(roleName);
                    }

                    // 标记超级管理员账号（ID为1）
                     if (i.getId() == 1) {
                         i.setIsSuperAdmin(true);
                     } else {
                         i.setIsSuperAdmin(false);
                     }

                    return i;
                }
        ).collect(Collectors.toList());
        // 将超级管理员（id=1）顶置显示
        List<GetUserListResponseDTO> superAdmins = collect1.stream().filter(i -> i.getId() == 1).toList();
        List<GetUserListResponseDTO> others = collect1.stream().filter(i -> i.getId() != 1).toList();
        List<GetUserListResponseDTO> reordered = Stream.concat(superAdmins.stream(), others.stream()).collect(Collectors.toList());
        getUserListResponseDTOPage.setRecords(reordered);
        return MyBatisPlusPageConverter.convertPage(getUserListResponseDTOPage, GetUserListResponseDTO.class);
    }

    @Override
    public Boolean deleteUser(Long id) {
        // 检查是否为超级管理员账号，防止删除
        checkSuperAdminProtection(id, "删除");
        
        Long startTime = System.nanoTime();
        int delete = userMapper.deleteById(id);

        // 删除用户delete_status(0为正常，1为逻辑删除)
        if (delete > 0) {
            // 检查用户是否在线
            if (StpUtil.isLogin(id)) {
                // 如果用户删除账号成功，则强制用户下线。
                StpUtil.kickout(id);
            }
        }

        Long endTime = System.nanoTime();

        AddOperateLogRequest addOperateLogRequest = new AddOperateLogRequest();
        addOperateLogRequest.setOperateModule("用户模块");
        addOperateLogRequest.setOperateName("删除用户");
        addOperateLogRequest.setOperateResult(Boolean.TRUE);
        addOperateLogRequest.setUserId(Long.valueOf(StpUtil.getLoginId().toString()));
        addOperateLogRequest.setOperateType(3);
        addOperateLogRequest.setIpAddress(ActionUtils.getIpInfo());
        addOperateLogRequest.setExplorer(ActionUtils.getExplorerInfo());
        addOperateLogRequest.setTimes(endTime - startTime);
        operateLogApi.addOperateLogRequest(addOperateLogRequest);

        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean edit(EditUserRequestDTO editUserRequestDTO) {
        // 检查是否为超级管理员账号，防止编辑
        checkSuperAdminProtection(editUserRequestDTO.getId(), "编辑");

        Long startTime = System.nanoTime();

        SmilePlusUser smilePlusUser = userMapper.selectById(editUserRequestDTO.getId());

        // 异步校验角色是否存在
        if (ObjectUtil.isNotNull(editUserRequestDTO.getRoleId())) {
            SmilePlusRole role = roleMapper.selectById(editUserRequestDTO.getRoleId());
            if (role == null) {
                throw new RuntimeException("角色已删除，请重新选择");
            }
        }

        UpdateWrapper<SmilePlusUser> updateWrapper = new UpdateWrapper<>();
        if (ObjectUtil.isNotNull(smilePlusUser)) {
            updateWrapper.eq(ObjectUtil.isNotNull(editUserRequestDTO.getId()),
                    "id", editUserRequestDTO.getId());
            updateWrapper.set(StrUtil.isNotBlank(editUserRequestDTO.getRealName()),
                    "real_name",
                    editUserRequestDTO.getRealName());

            updateWrapper.set(StrUtil.isNotBlank(editUserRequestDTO.getMobile()),
                    "mobile", editUserRequestDTO.getMobile());

            updateWrapper.set(ObjectUtil.isNotNull(editUserRequestDTO.getStatus())
                            && !StateConstant.NO_WRITE_STATE.equals(smilePlusUser.getStatus()), "status",
                    editUserRequestDTO.getStatus());

            updateWrapper.set(StrUtil.isNotBlank(editUserRequestDTO.getUserName()),
                    "user_name", editUserRequestDTO.getUserName());

            updateWrapper.set("modify_time", LocalDateTime.now());

            updateWrapper.set(ObjectUtil.isNotNull(editUserRequestDTO.getOrganizationId())
                    , "organization_id",
                    editUserRequestDTO.getOrganizationId());

            updateWrapper.set(StrUtil.isNotBlank(editUserRequestDTO.getImageUrl()),
                    "image_url", editUserRequestDTO.getImageUrl());

            updateWrapper.set(ObjectUtil.isNotNull(editUserRequestDTO.getRoleId()),
                    "role_id",
                    editUserRequestDTO.getRoleId());

            updateWrapper.set(StrUtil.isNotBlank(editUserRequestDTO.getMapCenterName()),
                    "map_center_name", editUserRequestDTO.getMapCenterName());

            updateWrapper.set(ObjectUtil.isNotNull(editUserRequestDTO.getLongitude()),
                    "longitude", editUserRequestDTO.getLongitude());

            updateWrapper.set(ObjectUtil.isNotNull(editUserRequestDTO.getLatitude()), "latitude", editUserRequestDTO.getLatitude());

            if (StrUtil.isNotBlank(editUserRequestDTO.getPassword())) {

                String s = MD5Util.md5WithSalt(editUserRequestDTO.getPassword(),
                        smilePlusUser.getSalt());
                updateWrapper.set(smilePlusUser.getStatus() != 3 &&
                        StrUtil.isNotBlank(editUserRequestDTO.getPassword()), "password", s);
            }
            // 基于传入或现有组织信息决定强制禁用逻辑
            Integer desiredStatus = editUserRequestDTO.getStatus();
            String actionLabel = desiredStatus == null ? "修改" : (desiredStatus == 1 ? "开启" : (desiredStatus == 2 ? "关闭" : "修改"));
            Long targetOrganizationId = ObjectUtil.isNotNull(editUserRequestDTO.getOrganizationId())
                    ? editUserRequestDTO.getOrganizationId()
                    : smilePlusUser.getOrganizationId();

            if (ObjectUtil.isNotNull(editUserRequestDTO.getOrganizationId())) {
                // 如果显式传入了 organizationId，则校验其是否存在
                SmilePlusOrganization specifiedOrganization = organizationMapper.selectById(editUserRequestDTO.getOrganizationId());
                if (ObjectUtil.isNull(specifiedOrganization)) {
                    throw new RuntimeException("该组织不存在!");
                }
                if (specifiedOrganization.getStatus() != null && !specifiedOrganization.getStatus()) {
                    // 组织被禁用了，账户不能开启
                    // 上级组织被禁用，若尝试开启账户则直接阻止并给出准确提示
                    if (desiredStatus != null && desiredStatus == 1) {
                        throw new RuntimeException("组织：" + specifiedOrganization.getOrganizationName() + " 处于禁用状态，无法" + actionLabel);
                    }
                }
            } else if (ObjectUtil.isNotNull(targetOrganizationId)) {
                // 未传入则采用用户当前组织来判断,账户不能开启
                SmilePlusOrganization currentOrganization = organizationMapper.selectById(targetOrganizationId);
                if (ObjectUtil.isNotNull(currentOrganization) && currentOrganization.getStatus() != null && !currentOrganization.getStatus()) {
                    if (desiredStatus != null && desiredStatus == 1) {
                        throw new RuntimeException("组织：" + currentOrganization.getOrganizationName() + " 处于禁用状态，无法" + actionLabel);
                    }
                }
            }

        }

        //userMapper.update(new SmilePlusUser(), updateWrapper);
        int update = userMapper.update(new SmilePlusUser(), updateWrapper);
        if (update > 0) {
            // 修改成功后，检查用户是否被禁用（无论是直接设置状态为2，还是因为组织被禁用而强制禁用）
            boolean isDisabled = false;
            
            // 情况1：直接设置用户状态为禁用
            if (editUserRequestDTO.getStatus() == 2) {
                isDisabled = true;
            }
            
            // 情况2：因为组织被禁用而强制禁用用户
            if (!isDisabled) {
                Long targetOrganizationId = ObjectUtil.isNotNull(editUserRequestDTO.getOrganizationId())
                        ? editUserRequestDTO.getOrganizationId()
                        : smilePlusUser.getOrganizationId();
                
                if (ObjectUtil.isNotNull(targetOrganizationId)) {
                    SmilePlusOrganization organization = organizationMapper.selectById(targetOrganizationId);
                    if (ObjectUtil.isNotNull(organization) && organization.getStatus() != null && !organization.getStatus()) {
                        isDisabled = true;
                    }
                }
            }
            
            // 如果用户被禁用且在线，强制用户下线
            if (isDisabled && StpUtil.isLogin(smilePlusUser.getId())) {
                StpUtil.kickout(smilePlusUser.getId());
            }
        }
        Long endTime = System.nanoTime();

        AddOperateLogRequest addOperateLogRequest = new AddOperateLogRequest();
        addOperateLogRequest.setOperateModule("用户模块");
        addOperateLogRequest.setOperateName("修改用户");
        addOperateLogRequest.setOperateResult(Boolean.TRUE);
        addOperateLogRequest.setUserId(Long.valueOf(StpUtil.getLoginId().toString()));
        addOperateLogRequest.setOperateType(2);
        addOperateLogRequest.setIpAddress(ActionUtils.getIpInfo());
        addOperateLogRequest.setExplorer(ActionUtils.getExplorerInfo());
        addOperateLogRequest.setTimes(endTime - startTime);
        operateLogApi.addOperateLogRequest(addOperateLogRequest);

        return Boolean.TRUE;
    }

    @Override
    public GetUserInfoByUserNameResponseDTO getUserInfoByUserName(GetUserInfoByUserNameRequestDTO getUserInfoByUserNameRequestDTO) {
        QueryWrapper<SmilePlusUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name", getUserInfoByUserNameRequestDTO.getUserName());
        queryWrapper.eq("delete_status", 0);
//        queryWrapper.eq("delete_status", Boolean.FALSE);
        SmilePlusUser smilePlusUser = userMapper.selectOne(queryWrapper);
//        GetUserInfoByUserNameResponseDTO getUserInfoByUserNameResponseDTO = new GetUserInfoByUserNameResponseDTO();
        GetUserInfoByUserNameResponseDTO getUserInfoByUserNameResponseDTO = BeanUtil.copyProperties(smilePlusUser, GetUserInfoByUserNameResponseDTO.class);
        return getUserInfoByUserNameResponseDTO;
    }

    @Override
    public GetUserByIdResponseDTO getUserById(Long id) {
        QueryWrapper<SmilePlusUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        queryWrapper.eq("delete_status", Boolean.FALSE);
        SmilePlusUser smilePlusUser = userMapper.selectOne(queryWrapper);
        GetUserByIdResponseDTO getUserByIdResponseDTO = new GetUserByIdResponseDTO();
        BeanUtil.copyProperties(smilePlusUser, getUserByIdResponseDTO);
        return getUserByIdResponseDTO;
    }

    @Override
    public GetUserSimpleInfoResponseDTO getUserSimpleInfo(Long id) {
        SmilePlusUser smilePlusUser = userMapper.selectById(id);
        GetUserSimpleInfoResponseDTO getUserSimpleInfoResponseDTO = BeanUtil.copyProperties(smilePlusUser, GetUserSimpleInfoResponseDTO.class);
        SmilePlusOrganization smilePlusOrganization = organizationMapper.selectById(smilePlusUser.getOrganizationId());
        if (ObjectUtil.isNotNull(smilePlusOrganization)) {
            getUserSimpleInfoResponseDTO.setOrganizationName(smilePlusOrganization.getOrganizationName());
        }
        return getUserSimpleInfoResponseDTO;
    }

    @Override
    public Map<Long, GetUserByIdResponseDTO> getUserByIds(List<Long> ids) {
        if (ObjectUtil.isNotNull(ids)) {

            List<SmilePlusUser> smilePlusUsers = userMapper.selectBatchIds(ids);
            return smilePlusUsers.stream().map(
                    i -> {
                        return BeanUtil.copyProperties(i, GetUserByIdResponseDTO.class);
                    }
            ).collect(toMap(GetUserByIdResponseDTO::getId, Function.identity(), (u1, u2) -> u1));
        } else {
            return new HashMap<>();
        }
    }

    @Override
    public void resetPassword(Long id) {
        // 检查是否为超级管理员账号，防止重置密码
        checkSuperAdminProtection(id, "重置密码");

        // 使用目标用户的盐生成重置密码摘要
        SmilePlusUser targetUser = userMapper.selectById(id);
        if (ObjectUtil.isNull(targetUser)) {
            throw new RuntimeException("用户不存在");
        }
        String hashed = MD5Util.md5WithSalt("FEISUAN888", targetUser.getSalt());

        UpdateWrapper<SmilePlusUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("password", hashed);
        userMapper.update(null, updateWrapper);
    }

}
